# -*- coding: utf-8 -*-
# !/usr/bin/python
__author__ = 'bitfeng'

from scrapyluke.commonfun import renameFile
import time
import datetime
import hashlib
import re
import sys
import os
import requests


reload(sys)						# 必须，不弄的话汉字有问题
sys.setdefaultencoding('utf8')  # 必须，不弄的话汉字有问题


def get_lfirst(l):
    if l.__len__() >= 1:
        result = l[0]
    else:
        result = None
    return result


def MD5(string):
    if isinstance(string, str):
        return hashlib.md5(string).hexdigest()
    elif isinstance(string, unicode):
        return hashlib.md5(string.encode('utf8')).hexdigest()
    else:
        return


class UUcode(object):

    # 所有请求的通用header：
    # request.Headers.Add("SID",软件id);
    # request.Headers.Add("HASH",md5(软件id+软件key.ToUpper()));
    # request.Headers.Add("UUVersion","1.0.0.1");
    # request.Headers.Add("UID",UserID);
    # //没有登录之前，UserID就用100。登录成功后，服务器会返回UserID，之后的请求就用服务器返回的UserID
    # request.Headers.Add("User-Agent", MD5(软件key.ToUpper() + UserID));
    # //没有登录之前，UserID就用100。登录成功后，服务器会返回UserID，之后的请求就用服务器返回的UserID
    def __init__(self, softID, softKey, userID='100', userName='name248', userPasswd='name,123'):
        self.userName = userName
        self.userPasswd = userPasswd
        self.softID = softID
        self.softKey = softKey
        self.userID = userID
        self.userKey = None
        self.mac = '00163e0101ee'.upper()
        self.login = False
        self.servers = None
        self.time_interval_getResult = 1000

    def initHeader(self, userID):
        header = {
            "SID": self.softID,
            "HASH": MD5(self.softID+self.softKey.upper()),
            "UUVersion": "1.0.0.1",
            "User-Agent": MD5(self.softKey.upper()+userID)
        }
        return header

    # 用户登录时候的特殊header：
    # 除了以上header之外，增加如下：
    # request.Headers.Add("KEY", MD5(软件key.ToUpper()+UserName.ToUpper())+MAC);
    # //MAC把特殊符号去掉，纯粹字母数字
    # request.Headers.Add("UUKEY", MD5(UserName.ToUpper() + MAC + 软件key.ToUpper()));
    # //MAC把特殊符号去掉，纯粹字母数字
    def getHeader_login(self, userName):
        header = self.initHeader(self.userID)
        header['UID'] = self.userID
        header['KEY'] = MD5(self.softKey.upper()+userName.upper())+self.mac
        header['UUKEY'] = MD5(userName.upper()+self.mac+self.softKey.upper())
        return header

    # 查分时候的特殊header:
    # request.Headers.Add("UUAgent", MD5(UserKEY.ToUpper() + UserID + 软件KEY));
    # request.Headers.Add("KEY", UserKey);
    def getHeader_balance(self, userKey):
        header = self.initHeader(self.userID)
        header['UID'] = self.userID
        header['KEY'] = userKey
        header['UUAgent'] = MD5(userKey.upper()+self.userID+self.softKey)
        return header

    # 1.获取(刷新)服务器列表:
    # Get http://common.taskok.com:9000/Service/ServerConfig.aspx
    #
    # /// 域名:端口:类型 例如
    # /// login.abc.com:8080:101,upload.abc.com:8080:102,result.abc.com:8080:103,
    # /// 类型101表示登录服务器，102表示上传服务器，103表a示获取结果服务器，104表示备份服务器
    # （当upload连续出错的话，调用备份服务器,备份服务器包含所有方法，登录，上传，取得结果）
    #
    # 1000,service.taskok.com:9000:101,upload.taskok.com:9000:102,code.taskok.com:9000:103,bak.taskok.com:104
    # 1000,表示间隔1000毫秒，请求一次getResult
    def refresh_servers(self, url='http://common.taskok.com:9000/Service/ServerConfig.aspx'):
        header = self.initHeader(userID='100')
        res = requests.get(url=url, headers=header)
        if res.status_code == 200 and ':101' in res.text:
            self.time_interval_getResult = get_lfirst(res.text.split(','))
            self.servers = {
                'login_server': get_lfirst(re.compile('(?<=,)[^,]*?(?=:101)').findall(res.text)),
                'upload_server': get_lfirst(re.compile('(?<=,)[^,]*?(?=:102)').findall(res.text)),
                'getResult_server': get_lfirst(re.compile('(?<=,)[^,]*?(?=:103)').findall(res.text)),
                'backup_server': get_lfirst(re.compile('(?<=,)[^,]*?(?=:104)').findall(res.text)),
            }
            suc = True
        else:
            suc = False
        return suc, res

    # 2.登录
    # Get http://login.abc.com/Upload/UULogin.aspx?U={0}&p={1}
    # {0}为用户名 {1}为密码的md5值
    #
    # 返回结果：
    # 成功返回UserKey(保存下来，后面上传图片的时候需要这个参数), UserKey的格式为 UserID_随机串, 取出第一个下划线之前的内容即为UserID。
    # 失败返回错误代码，错误代码均为负数，官方网站(http://www.uuwise.com/allErrorCode.html)上面有每一个错误代码的具体含义
    def login_servers(self, userName, userPasswd):
        url = 'http://%s/Upload/UULogin.aspx' % self.servers['login_server']
        header = self.getHeader_login(userName)
        param = {'U': userName, 'p': MD5(userPasswd)}

        res = requests.get(url=url, headers=header, params=param)
        if res.status_code == 200:
            if '_' in res.text:
                self.userID = res.text.split('_')[0]
                self.userKey = res.text
            return True, res
        else:
            return False, res

    # 3.查分
    # Get http://login.abc.com/Upload/GetPoint.aspx?U={0}&p={1}
    # {0}为用户名 {1}为密码的md5值
    #
    # 返回结果：
    # 成功返回当前的用户点数
    # 失败返回错误代码
    def get_balance(self, login_server, userName, userPasswd):
        if self.userKey:
            url = 'http://%s/Upload/UULogin.aspx?U=%s&p=%s' % (login_server, userName, MD5(userPasswd))
            response, content = self.h.request(uri=url, headers=self.getHeader_balance(userKey=self.userKey))
            return response, content
        else:
            return

    # 4.上传图片
    # 在上传图片之前，需要请求 http://common.taskok.com:9000/Service/ServerConfig.aspx 来刷新服务器列表
    # Post http://upload.abc.com/Upload/Processing.aspx
    #
    # 数据：
    # KEY：  		UserKey.ToUpper()  登录返回的数据
    # SID:		软件id
    # SKEY:		求MD5(UserKey.ToLower()+软件id+软件key)
    # Version:	100
    # TimeOut:	超时时间，单位为毫秒，必须大于20000
    # Type:		验证码的CodeType，详见：http://www.uuwise.com/price.html
    # IMG：   	图片文件
    # GUID   		图片文件的Md5()
    #
    # 返回结果：
    #
    #
    # 成功返回：
    # 验证码id 			//这个时候表示无结果，需要请求getresult
    # 或者
    # 验证码id|Result 	//Result即为识别结果
    # 例如：12130123|ssdd
    #
    # 失败返回错误代码
    def upload_img(self, img, codeType, guid, getRe_max):
        id = None
        result = None
        suc, _ = self.refresh_servers()
        if suc:
            if self.userKey is not None:
                try:
                    url = 'http://%s/Upload/Processing.aspx' % self.servers['upload_server']
                    header = self.initHeader(self.userID)
                    header['SID'] = self.userID
                    data = {
                        'KEY': self.userKey.upper(),
                        'SID': self.softID,
                        'SKey': MD5(self.userKey.lower()+self.softID+self.softKey),
                        'Version': 100,
                        'Type': codeType,
                        'GUID': MD5(guid)
                    }
                    print 'Start identifying code ...... [%s]' % datetime.datetime.now()
                    res = requests.post(url=url, data=data, files={'IMG': img}, timeout=60)
                    # print res.text
                    if res.status_code == 200:
                        if res.text is not None:
                            if '|' in res.text:
                                id, result = res.text.split('|')[0:2]
                            else:
                                id = res.text
                                for i in xrange(getRe_max):
                                    result = self.get_result(id)
                                    print '%d getting id-%s result: %s' % (i, res.text, result)
                                    if result != '-3':
                                        print 'Got Result: %s  [%s]' % (result, datetime.datetime.now())
                                        break
                                    time.sleep(float(self.time_interval_getResult)/1000)
                                return [id, result]
                        else:
                            print 'Upload IMG : response.text is None'
                    else:
                        print 'Upload IMG : Error %d' % res.status_code
                except Exception, e:
                    print str(e)
        return [id, result]

    # 5. 获取识别结果
    # GET http://result.abc.com/Upload/GetResult.aspx?key={0}&ID={1}
    # {0}为UserKey, {1}为验证码id
    #
    # 返回结果:
    # 如果返回结果为-3，则代表服务器还未识别完成，间隔1000毫秒，循环请求getResult
    # 成功返回验证码识别结果，错误返回错误代码
    def get_result(self, id):
        result = None
        url = 'http://%s/Upload/GetResult.aspx' % self.servers['getResult_server']
        param = {'KEY': self.userKey, 'ID': id}
        res = requests.get(url=url, headers=self.initHeader(self.userID), params=param)
        if res.status_code == 200:
            result = res.text
        return result

    def get_code_url(self, code_url):
        res = requests.get(code_url)
        print res.status_code
        if res.status_code == 200:
            return res.content, str(int(time.time()))+'.jpg'
        else:
            return None, None

    def store_code(self, img_content, filename, path):
        abspath = os.path.join(path, filename)
        f = open(abspath, 'wb')
        f.write(img_content)
        f.close()
        return abspath

    def get_check_code(self, code_url, store_path, code_type, getRe_max):
        img_content, filename = self.get_code_url(code_url)
        if img_content:
            img_abspath = self.store_code(img_content, filename, store_path)
            return check_code(img_abspath, code_type, getRe_max)
        else:
            return

    def check_code(self, img_abspath, code_type, getRe_max):
        # uu = UUcode('109521', '3c8906d3666e44bb9c961e1647126dbc')
        self.refresh_servers()
        suc, _ = self.login_servers(userName=self.userName, userPasswd=self.userPasswd)
        if suc:
            f = open(img_abspath, 'rb')
            strRead = f.read()
            f.close()
            result = self.upload_img(
                img=open(img_abspath, 'rb'),
                codeType=code_type,
                guid=strRead,
                getRe_max=getRe_max
            )
            return result
        else:
            return


class InitCode(object):

    def __init__(self, session=None):
        self.s = session

    def get_code(self, url):
        tm = int(time.time())
        param = {'currentTimeMillis': tm}
        res = requests.get(url, params=param)
        return res.content, str(tm)+'.jpg'

    def store_code(self, content, filename, path):
        abspath = os.path.join(path, filename)
        f = open(abspath, 'wb')
        f.write(content)
        f.close()
        return abspath

    def get_code_session(self, url, param=None):
        if param:
            res = self.s.get(url, params=param)
        else:
            res = self.s.get(url)
        return res.content, renameFile(url)+'.jpg'


def check_code(img_abspath, code_type, getRe_max):

    uu = UUcode('109521', '3c8906d3666e44bb9c961e1647126dbc')
    uu.refresh_servers()
    suc, _ = uu.login_servers(userName='name248', userPasswd='name,123')
    if suc:
        f = open(img_abspath, 'rb')
        strRead = f.read()
        f.close()
        result = uu.upload_img(
            img=open(img_abspath, 'rb'),
            codeType=code_type,
            guid=strRead,
            getRe_max=getRe_max
        )
        return result
    else:
        return


if __name__ == '__main__':
    uu = UUcode('109521', '3c8906d3666e44bb9c961e1647126dbc')
    print uu.get_check_code(code_url='http://www.jsgsj.gov.cn:58888/province/rand_img.jsp?type=8',
                            store_path='/home/li-x/imgs',
                            code_type=3006,
                            getRe_max=30)